using System;
using System.Text;

using System.IO;
using System.Collections;
using System.Collections.Generic;

namespace Tools.SubStream {

    /// <summary>
    /// 
    /// </summary>
    public class StreamMuxerException : Exception {
        /// <summary>
        /// 
        /// </summary>
        public enum Kind { General, RangeError };

        /// <summary>
        /// 
        /// </summary>
        public Kind kind;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="kind"></param>
        public StreamMuxerException ( String message, StreamMuxerException.Kind kind )
            : base( message ) {
            this.kind = kind;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        public StreamMuxerException ( String message )
            : base( message ) {
            this.kind = Kind.General;
        }



    }

    /// <summary>
    /// 
    /// </summary>
    public class StreamMuxer {

        /// <summary>
        /// 
        /// </summary>
        protected Hashtable subStreams = new Hashtable( );

        /// <summary>
        /// 
        /// </summary>
        protected System.IO.Stream innerStream;

        /// <summary>
        /// gets 
        /// </summary>
        public System.IO.Stream InnerStream {
            get {
                if ( this.innerStream == null ) {
                    throw new StreamMuxerException( "InnerStream not initialised" );
                };
                return this.innerStream;

            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="masterStream"></param>
        public StreamMuxer ( System.IO.Stream masterStream ) {
            this.innerStream = System.IO.Stream.Synchronized( masterStream );

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="range"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        protected MuxerSubStream MakeSubStream ( Range range, String name ) {
            return new MuxerSubStream( this, range, name );
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="range"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public MuxerSubStream AddSubStream ( Range range, String name ) {
            MuxerSubStream substr = this.MakeSubStream( range, name );
            this.subStreams.Add( name, substr );
            return substr;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public MuxerSubStream this[String name] {
            get {
                return this.GetSubStream( name );
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public MuxerSubStream GetSubStream ( String name ) {
            if ( this.subStreams.ContainsKey( name ) ) {
                return ( MuxerSubStream ) this.subStreams[name];
            } else {
                throw new StreamMuxerException( "no requested substream" );
            }
        }

        public long Length {
            get {
                return this.InnerStream.Length;
            }
        }
    }
}
